package org.mrjbee.share.it.easy.client.daemon;
import org.mrjbee.share.it.easy.client.daemon.clipboard.ClipboardManager;
import org.mrjbee.share.it.easy.client.daemon.command.Command;
import org.mrjbee.share.it.easy.client.daemon.http.GAEHttpManager;
import org.mrjbee.share.it.easy.client.daemon.http.HttpManager;
import org.mrjbee.share.it.easy.client.daemon.http.SimpleHttpManager;
import org.mrjbee.share.it.easy.client.daemon.mbeans.MBeansManager;
import org.mrjbee.share.it.easy.client.daemon.notification.NotificationManager;

public class Daemon {
	
	private Command command = new Command();
	private boolean shouldContinue = true;
	private ConfigurationProvider conf;
	private MBeansManager mBeansManager = new MBeansManager();
	private HttpManager httpManager;
	private ClipboardManager clipboardManager = new ClipboardManager();
	private NotificationManager notificationManager = new NotificationManager();
	
	public Daemon(ConfigurationProvider configuration) {
		conf = configuration;
	}

	public void start() {
		Log.SYS.info("Starting daemon");
		shouldContinue = doInit();
		while(shouldContinue ){
			synchronized (command) {
				try {
					Log.SYS.debug("Waiting for a command...");
					command.wait();
				} catch (InterruptedException e) {
					Log.SYS.fatal("Fatal error during waiting for a command.", e);
					doGracefulShutdown(true);
				}
				
				Log.SYS.debug("Command type to execute:"+command.getType());
				command.setInProgress(true);
				switch (command.getType()) {
				case PUBLISH:
						doPublish();
					break;
				case GRAB:
						doGrab();
					break;	
				case STOP:
					//set exit flag
					shouldContinue = false;
					break;
				default:
					break;
				}
				command.setInProgress(false);
			}
		}
		doGracefulShutdown(true);
	}

	private boolean doInit() {
		try {
			notificationManager.init(conf);
			mBeansManager.openInterface(command);
		} catch (Exception e) {
			Log.SYS.error("Error during inititing...",e);
			return false;
		}
		try {
			if (conf.isGAEManagerRequired()){
				httpManager = new GAEHttpManager();
			} else {
				httpManager = new SimpleHttpManager();
			}
			httpManager.initClient(conf);
		} catch (Exception e) {
			Log.SYS.error("Error during HTTP Manager inititing...",e);
			notificationManager.notifyFaild("Clipboarding daemon start");
			return false;
		}
		
		notificationManager.notify("Clipboarding daemon", "Started...");
		return true;
	}

	private void doGrab() {
		String sharedClipboard = httpManager.grabString();
		if (sharedClipboard !=null){
			clipboardManager.setClipboardContents(sharedClipboard);
			sharedClipboard = prepeareNotificationBody(sharedClipboard);
			notificationManager.notify("Clipboard Grabbing",sharedClipboard);
		} else {
			notificationManager.notifyFaild("Clipboard Grabbing");
		}
	}

	private String prepeareNotificationBody(String sharedClipboard) {
		sharedClipboard = sharedClipboard.replace("\t", " ");
		sharedClipboard = sharedClipboard.replace("\n", " ");
		sharedClipboard = sharedClipboard.replace(";", " ");
		if (sharedClipboard.length() > 30){
			sharedClipboard = sharedClipboard.substring(0,30)+"...";
		}
		return sharedClipboard;
	}
	
	
	private void doPublish() {
		String st = clipboardManager.getClipboardContents().trim();
		if (st.isEmpty()){
			notificationManager.notify("Clipboard Publishing", "Nothing to publish...");
			return;
		}
		if (httpManager.publishString(st)){
			st =prepeareNotificationBody(st);
			notificationManager.notify("Clipboard Publishing", st);
		} else {
			notificationManager.notifyFaild("Clipboard Publishing");
		}
	}

	public void doGracefulShutdown(boolean force) {
		Log.SYS.info("Daemon going to shutdown.");
		if (httpManager!=null)
			httpManager.dropClient();
		if (notificationManager != null)
			notificationManager.deinit(conf);
		Log.SYS.info("Daemon is shutdown.");
	}

}
